"""
自动备份数据模型模块

此模块定义了自动备份功能中使用的数据结构和模型类，用于数据表示和验证。
"""

import time
from typing import Dict, Any, Optional
from datetime import datetime
from logger_module import log_warning


class BackupSettings:
    """
    备份设置数据模型
    
    包含自动备份的所有配置项，提供数据验证和序列化功能。
    """
    
    # 有效的备份频率选项
    VALID_FREQUENCIES = ['每天', '每周', '每月']
    
    def __init__(self,
                 enabled: bool = False,
                 frequency: str = '每天',
                 backup_time: str = '00:00',
                 backup_path: str = ''):
        """
        初始化备份设置
        
        Args:
            enabled: 是否启用自动备份
            frequency: 备份频率，必须是VALID_FREQUENCIES中的值
            backup_time: 备份时间，格式为HH:MM
            backup_path: 备份文件保存路径
        """
        self.enabled = enabled
        self.frequency = frequency
        self.backup_time = backup_time
        self.backup_path = backup_path
        self.last_backup_time: Optional[datetime] = None
        self.next_backup_time: Optional[datetime] = None
    
    def to_dict(self) -> Dict[str, Any]:
        """
        将设置转换为字典格式
        
        Returns:
            Dict: 包含所有设置项的字典
        """
        result = {
            'enabled': self.enabled,
            'frequency': self.frequency,
            'backup_time': self.backup_time,
            'backup_path': self.backup_path
        }
        
        # 添加可选字段
        if self.last_backup_time:
            result['last_backup_time'] = self.last_backup_time.isoformat()
        if self.next_backup_time:
            result['next_backup_time'] = self.next_backup_time.isoformat()
        
        return result
    
    def from_dict(self, data: Dict[str, Any]) -> 'BackupSettings':
        """
        从字典加载设置
        
        Args:
            data: 包含设置的字典
        
        Returns:
            BackupSettings: 更新后的实例（支持链式调用）
        """
        self.enabled = data.get('enabled', False)
        self.frequency = data.get('frequency', '每天')
        self.backup_time = data.get('backup_time', '00:00')
        self.backup_path = data.get('backup_path', '')
        
        # 处理时间字段
        if 'last_backup_time' in data:
            try:
                if isinstance(data['last_backup_time'], str):
                    self.last_backup_time = datetime.fromisoformat(data['last_backup_time'])
                elif isinstance(data['last_backup_time'], float):
                    self.last_backup_time = datetime.fromtimestamp(data['last_backup_time'])
            except Exception as e:
                log_warning(f"解析last_backup_time失败: {str(e)}")
        
        if 'next_backup_time' in data:
            try:
                if isinstance(data['next_backup_time'], str):
                    self.next_backup_time = datetime.fromisoformat(data['next_backup_time'])
                elif isinstance(data['next_backup_time'], float):
                    self.next_backup_time = datetime.fromtimestamp(data['next_backup_time'])
            except Exception as e:
                log_warning(f"解析next_backup_time失败: {str(e)}")
        
        return self
    
    @classmethod
    def create_from_dict(cls, data: Dict[str, Any]) -> 'BackupSettings':
        """
        从字典创建BackupSettings实例
        
        Args:
            data: 包含设置的字典
        
        Returns:
            BackupSettings: 创建的实例
        """
        instance = cls(
            enabled=data.get('enabled', False),
            frequency=data.get('frequency', '每天'),
            backup_time=data.get('backup_time', '00:00'),
            backup_path=data.get('backup_path', '')
        )
        
        # 处理时间字段
        if 'last_backup_time' in data:
            try:
                if isinstance(data['last_backup_time'], str):
                    instance.last_backup_time = datetime.fromisoformat(data['last_backup_time'])
                elif isinstance(data['last_backup_time'], float):
                    instance.last_backup_time = datetime.fromtimestamp(data['last_backup_time'])
            except Exception as e:
                log_warning(f"解析last_backup_time失败: {str(e)}")
        
        if 'next_backup_time' in data:
            try:
                if isinstance(data['next_backup_time'], str):
                    instance.next_backup_time = datetime.fromisoformat(data['next_backup_time'])
                elif isinstance(data['next_backup_time'], float):
                    instance.next_backup_time = datetime.fromtimestamp(data['next_backup_time'])
            except Exception as e:
                log_warning(f"解析next_backup_time失败: {str(e)}")
        
        return instance
    
    def validate(self) -> Dict[str, str]:
        """
        验证设置的有效性
        
        Returns:
            Dict: 包含验证结果的字典，键为字段名，值为错误消息或空字符串
        """
        errors = {}
        
        # 验证频率
        if self.frequency not in self.VALID_FREQUENCIES:
            errors['frequency'] = f'无效的备份频率，必须是: {"、".join(self.VALID_FREQUENCIES)}'
        
        # 验证时间格式
        try:
            parts = self.backup_time.split(':')
            if len(parts) != 2:
                errors['backup_time'] = '时间格式无效，应为HH:MM格式'
            else:
                hour, minute = int(parts[0]), int(parts[1])
                if not (0 <= hour <= 23 and 0 <= minute <= 59):
                    errors['backup_time'] = '时间超出有效范围(00:00-23:59)'
        except ValueError:
            errors['backup_time'] = '时间格式无效，小时和分钟必须是数字'
        except Exception:
            errors['backup_time'] = '时间格式无效'
        
        # 如果启用了备份，还需要验证路径
        if self.enabled and not self.backup_path:
            errors['backup_path'] = '启用自动备份时必须设置备份路径'
        
        return errors
    
    def is_valid(self) -> bool:
        """
        检查设置是否有效
        
        Returns:
            bool: 设置是否有效
        """
        return len(self.validate()) == 0
    
    def get_validation_error_message(self) -> Optional[str]:
        """
        获取验证错误消息
        
        Returns:
            str: 错误消息，如果没有错误则返回None
        """
        errors = self.validate()
        if errors:
            return '; '.join([f'{field}: {msg}' for field, msg in errors.items()])
        return None
    
    def update(self, **kwargs):
        """
        更新设置项
        
        Args:
            **kwargs: 要更新的设置项
        """
        if 'enabled' in kwargs:
            self.enabled = kwargs['enabled']
        if 'frequency' in kwargs:
            self.frequency = kwargs['frequency']
        if 'backup_time' in kwargs:
            self.backup_time = kwargs['backup_time']
        if 'backup_path' in kwargs:
            self.backup_path = kwargs['backup_path']
    
    def __str__(self) -> str:
        """
        返回设置的字符串表示
        
        Returns:
            str: 设置的字符串表示
        """
        status = "启用" if self.enabled else "禁用"
        last_backup = self.last_backup_time.strftime("%Y-%m-%d %H:%M:%S") if self.last_backup_time else "从未备份"
        next_backup = self.next_backup_time.strftime("%Y-%m-%d %H:%M:%S") if self.next_backup_time else "未设置"
        
        return (
            f"备份设置:\n"
            f"  - 状态: {status}\n"
            f"  - 频率: {self.frequency}\n"
            f"  - 时间: {self.backup_time}\n"
            f"  - 路径: {self.backup_path}\n"
            f"  - 上次备份: {last_backup}\n"
            f"  - 下次备份: {next_backup}"
        )
    
    def __repr__(self) -> str:
        """
        返回设置的机器可读表示
        
        Returns:
            str: 设置的机器可读表示
        """
        return self.__str__()


class BackupRecord:
    """
    备份记录数据模型
    
    用于表示一次备份操作的记录信息。
    """
    
    def __init__(self,
                 backup_path: str,
                 timestamp: float = None,
                 success: bool = True,
                 error_message: str = '',
                 file_size: int = None):
        """
        初始化备份记录
        
        Args:
            backup_path: 备份文件路径
            timestamp: 备份时间戳，默认为当前时间
            success: 备份是否成功
            error_message: 错误消息，如果备份失败
            file_size: 备份文件大小（字节）
        """
        self.backup_path = backup_path
        self.timestamp = timestamp or time.time()
        self.success = success
        self.error_message = error_message
        self.file_size = file_size
        self.duration = None  # 备份持续时间（秒）
    
    def to_dict(self) -> Dict[str, Any]:
        """
        将记录转换为字典格式
        
        Returns:
            Dict: 包含所有记录项的字典
        """
        from datetime import datetime
        
        return {
            'backup_path': self.backup_path,
            'timestamp': self.timestamp,
            'datetime': datetime.fromtimestamp(self.timestamp).strftime('%Y-%m-%d %H:%M:%S'),
            'success': self.success,
            'error_message': self.error_message,
            'file_size': self.file_size,
            'duration': self.duration
        }
    
    def get_formatted_time(self, format_str: str = '%Y-%m-%d %H:%M:%S') -> str:
        """
        获取格式化的时间字符串
        
        Args:
            format_str: 时间格式字符串
        
        Returns:
            str: 格式化的时间字符串
        """
        from datetime import datetime
        try:
            return datetime.fromtimestamp(self.timestamp).strftime(format_str)
        except Exception as e:
            log_warning(f"格式化时间戳失败: {str(e)}")
            return f"{self.timestamp}"
    
    def get_file_size_str(self) -> str:
        """
        获取格式化的文件大小字符串
        
        Returns:
            str: 格式化的文件大小
        """
        if self.file_size is None:
            return "未知"
        
        size = float(self.file_size)
        for unit in ['B', 'KB', 'MB', 'GB']:
            if size < 1024.0:
                return f"{size:.2f} {unit}"
            size /= 1024.0
        return f"{size:.2f} TB"
    
    def __str__(self) -> str:
        """
        返回记录的字符串表示
        
        Returns:
            str: 记录的字符串表示
        """
        status = "成功" if self.success else f"失败: {self.error_message}"
        result = f"备份记录[{self.get_formatted_time()}]: {self.backup_path} ({status})"
        
        if self.file_size:
            result += f" - 大小: {self.get_file_size_str()}"
        
        if self.duration:
            result += f" - 耗时: {self.duration:.2f}秒"
        
        return result